﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using RoboTrocity;
using RoboTrocity.Code.ObjectStates;

namespace RoboTrocity {
	class CollisionHandler {

		public static void HandleCollision(MovableObject mObject, GameObject gObject) {
			if (mObject is Entity) {
				if (gObject is Terrain) {
					mObject.collideWith((Terrain)gObject);
					//CollisionHandler.HandleCollision((Entity)mObject, (Terrain)gObject);
				}
				if (gObject is Entity) {
					CollisionHandler.HandleCollision((Entity)mObject, (Entity)gObject);
				}
			}
			
		}

		public static void HandleCollision(Entity entity, Terrain terrain) {
			if ((terrain.Bounds.Right >= entity.Bounds.Left && terrain.Bounds.Right <= entity.Bounds.Right) ||
				(terrain.Bounds.Left >= entity.Bounds.Left && terrain.Bounds.Left <= entity.Bounds.Right)) {
					if (terrain is TerrainSlope) {
						if (terrain.Bounds.Bottom >= entity.Bounds.Top) {
							CollisionHandler.HandleCollision(entity, (TerrainSlope)terrain);
						}
						return;
					}
					//normal terrain block
					if (!entity.OnSlope ) {
						Vector2 movement = CollisionHandler.FindMovementOffset(entity.Bounds, terrain.Bounds);
						
						if (movement.X != 0) {
							//entity.setVelocityX((int)(entity.Velocity.X + movement.X - Math.Sign(movement.Y)));
							//entity.setPositionX((int)(entity.Position.X + entity.Velocity.X + movement.X));
							if (movement.X > 0) {
								entity.setPositionX(terrain.Bounds.Right + 1);
							} else {
								entity.setPositionX(terrain.Bounds.Left - entity.Width - 1);
							}
							entity.setVelocityX(0);
						}
						if (movement.Y != 0) {
							if (movement.Y > 0 && entity.CurrentState is JumpState) { //colliding with ceiling
								entity.setPositionY(terrain.Bounds.Bottom + 1);
							} else if (movement.Y < 0) {
								entity.setPositionY(terrain.Bounds.Top - entity.Height);
							}
							entity.setVelocityY(0);
						}
						/*if (movement.Y != 0 && (entity.State.Type != TEMPObjectState.StateType.JUMPING || movement.Y > 0) ) {
							//entity.setVelocityY((int)(entity.Velocity.Y + movement.Y - Math.Sign(movement.Y)));
							entity.setPositionY((int)(entity.Position.Y + entity.Velocity.Y + movement.Y - Math.Sign(movement.Y)));
							entity.setVelocityY((movement.Y > 0 ? 1 : 0)); //this line prevents getting your head stuck
						}*/
					 
					}
				}
		}

		/*public static void HandleCollision(Entity entity, TerrainSlope slope) {
			//Check if the bottom-center of the entity is touching the ramp
			if (entity.BottomCenter.X >= slope.Bounds.Left && entity.BottomCenter.X <= slope.Bounds.Right) {
				//now see if the bottom-center of the entity is inside of the slope
				int height = slope.Height;
				int width = slope.Width;
				float relativeInsideX = entity.BottomCenter.X - slope.Position.X;
				float relativeY = entity.BottomCenter.Y - slope.Position.Y; 
				float percentageInside = relativeInsideX / width;
				float correctYPosition = height - (relativeInsideX * slope.Slope);
				//if the slope is from top-left to bottom right, switch the percentages
				if (slope.Slope < 0) { 
					correctYPosition = Math.Abs(relativeInsideX * slope.Slope);
				}
				if (!entity.isAirborne() || (relativeY > correctYPosition)) {
					entity.setPositionY((int)(correctYPosition + slope.Position.Y - entity.Height));
					entity.setVelocityY(0);
					entity.OnSlope = true;
				} 
			}

		}*/

		public static void HandleCollision(Entity entity, Bullet bullet) {
			

		}

		public static Vector2 FindMovementOffset(CollisionBox mObjectBounds, CollisionBox otherBounds) {
			// Our displacement result vector containing the translation (movement) information
			// that resolves our intersection.
			Vector2 result = Vector2.Zero;

			// This is re-used to calculate the difference in distance between sides.
			float difference = 0.0f;

			// This stores the absolute minimum distance we'll need to separate our colliding object.
			float minimumTranslationDistance = 0.0f;

			// Axis stores the value of X or Y.  X = 0, Y = 1.
			// Side stores the value of left (-1) or right (+1).
			// They're used later in calculating the result vector.
			int axis = 0, side = 0;
			
			// Left
			difference = mObjectBounds.Right - otherBounds.Left;
			if (difference < 0.0f) { return Vector2.Zero; }

			minimumTranslationDistance = difference;
			axis = 0;
			side = -1;

			// Right
			difference = otherBounds.Right - mObjectBounds.Left;
			if (difference < 0.0f) { return Vector2.Zero; }
			if (difference < minimumTranslationDistance) {
				minimumTranslationDistance = difference;
				axis = 0;
				side = 1;
			}
			// Down
			difference = mObjectBounds.Bottom - otherBounds.Top;
			float yDiff = difference;
			if (difference < 0.0f) { return Vector2.Zero; }
			if (difference < minimumTranslationDistance + 1) {
				minimumTranslationDistance = difference;
				axis = 1;
				side = -1;
			}
			// Up
			difference = otherBounds.Bottom - mObjectBounds.Top;
			if (difference < 0.0f) { return Vector2.Zero; }
			if (difference < minimumTranslationDistance) {
				minimumTranslationDistance = difference;
				axis = 1;
				side = 1;
			}
			// Intersection occurred:
			if (axis == 1) { 
				result.Y = (float)side * (minimumTranslationDistance + 1); 
			} // Y Axis 
			else { 
				result.X = (float)side * (minimumTranslationDistance + 1);
			} // X Axis
			
			return result;
		}

		public static void HandleCollision(Entity ent1, Entity ent2) {
			//handle entity collision here. Most collisions will likely be by two enemies
			
		}
		

//		public static bool Intersects(MovableObject mObject, GameObject gObject) {
//			// check if two Rectangles intersect
//			CollisionBox a = mObject.Bounds;
//			CollisionBox b = gObject.Bounds;
//			return (a.Right >= b.Left && a.Left <= b.Right &&
//					a.Bottom >= b.Top && a.Top <= b.Bottom);
//		}

		public static bool PointAndSquareIntersects(Point point, CollisionBox square) {
			return (point.X >= square.Left && point.X <= square.Right &&
					point.Y >= square.Top && point.Y <= square.Bottom);
		}
/*
		public static bool RectAndRectIntersects(CollisionBox rect1, CollisionBox rect2) {
			return !(rect1.Left >= rect2.Right || rect2.Left >= rect1.Right ||
				rect1.Top >= rect2.Bottom || rect2.Top >= rect1.Bottom);
		}
		*/
 }

}